package com.peas.platform.module.icims.contract.initial.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.RowUtil;
import cn.hutool.poi.excel.WorkbookUtil;
import cn.hutool.poi.excel.cell.CellUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.peas.platform.common.core.constant.Constants;
import com.peas.platform.common.core.dto.ResponseDto;
import com.peas.platform.common.core.utils.ExcelTool;
import com.peas.platform.common.core.utils.ExceptionUtil;
import com.peas.platform.common.core.utils.ValidatorUtil;
import com.peas.platform.framework.mybatisplus.utils.PageUtil;
import com.peas.platform.module.icims.contract.initial.controller.criteria.ContractInitialCompleteCriteria;
import com.peas.platform.module.icims.contract.initial.controller.vo.ContractInitialCompleteVo;
import com.peas.platform.module.icims.contract.initial.dto.ContractInitialCompleteDto;
import com.peas.platform.module.icims.contract.initial.service.ContractInitialCompleteService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.SneakyThrows;
import org.apache.poi.ss.usermodel.*;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Api(tags = "【初始合同执行-完结】接口")
@RestController
@RequestMapping("/api/v1/contract-initial-complete")
public class ContractInitialCompleteController {

    @Resource
    private HttpServletRequest request;
    @Resource
    private HttpServletResponse response;
    @Resource
    private ContractInitialCompleteService contractInitialCompleteService;

    @ApiOperation(value = "添加初始合同执行-完结")
    @PostMapping("/add")
    public ResponseDto<Integer> add(@RequestBody @Valid ContractInitialCompleteVo contractInitialCompleteVo) {
        ContractInitialCompleteDto dto = BeanUtil.copyProperties(contractInitialCompleteVo, ContractInitialCompleteDto.class);
        int result = contractInitialCompleteService.save(dto);
        return ResponseDto.getSuccessResponseDto(result);
    }

    @ApiOperation(value = "删除初始合同执行-完结")
    @DeleteMapping("/{id}")
    public ResponseDto<Integer> delete(@ApiParam(name = "id", value = "要删除的数据主键ID", example = "1") @PathVariable("id") Long id) {
        int result = contractInitialCompleteService.removeById(id);
        return ResponseDto.getSuccessResponseDto(result);
    }

    @ApiOperation(value = "修改初始合同执行-完结")
    @PutMapping("/modify")
    public ResponseDto<Integer> modify(@RequestBody @Valid ContractInitialCompleteVo contractInitialCompleteVo) {
        ContractInitialCompleteDto dto = BeanUtil.copyProperties(contractInitialCompleteVo, ContractInitialCompleteDto.class);
        int result = contractInitialCompleteService.updateById(dto);
        return ResponseDto.getSuccessResponseDto(result);
    }

    @ApiOperation(value = "根据ID查询初始合同执行-完结")
    @GetMapping("/{id}")
    public ResponseDto<ContractInitialCompleteVo> id(@ApiParam(name = "id", value = "查询的主键ID", example = "1") @PathVariable("id") Long id) {
        ContractInitialCompleteDto dto = contractInitialCompleteService.getById(id);
        ContractInitialCompleteVo vo = BeanUtil.copyProperties(dto, ContractInitialCompleteVo.class);
        return ResponseDto.getSuccessResponseDto(vo);
    }

    @ApiOperation(value = "根据多个ID查询初始合同执行-完结")
    @GetMapping("/ids")
    public ResponseDto<List<ContractInitialCompleteVo>> ids(@ApiParam(name = "ids", value = "查询多个主键的id，用半角逗号分隔", example = "1,2,3,4,5") String ids) {
        List<Long> list = new ArrayList<>();
        CollUtil.forEach(StrUtil.split(ids, ','), (CollUtil.Consumer<String>) (id, index) -> list.add(Long.parseLong(id)));
        List<ContractInitialCompleteDto> result = contractInitialCompleteService.listByIds(list);
        List<ContractInitialCompleteVo> r = BeanUtil.copyToList(result, ContractInitialCompleteVo.class);
        return ResponseDto.getSuccessResponseDto(r);
    }

    @ApiOperation(value = "根据某个字段查询初始合同执行-完结")
    @GetMapping("/listByField")
    public ResponseDto<List<ContractInitialCompleteVo>> listByField(@ApiParam(name = "field", value = "要查询的字段", example = "id") String field,
                                                    @ApiParam(name = "values", value = "字段对应的多个值，用半角逗号分隔", example = "1,2,3,4,5") String values) {
        List<String> list = StrUtil.split(values, StrUtil.COMMA);
        List<ContractInitialCompleteDto> result = contractInitialCompleteService.listByField(field, list);
        List<ContractInitialCompleteVo> r = BeanUtil.copyToList(result, ContractInitialCompleteVo.class);
        return ResponseDto.getSuccessResponseDto(r);
    }

    @ApiOperation(value = "根据条件查询初始合同执行-完结（分页）")
    @GetMapping("/page")
    public ResponseDto<Page<ContractInitialCompleteVo>> page(ContractInitialCompleteCriteria condition,
                                 @ApiParam(name = "pageNum", value = "分页页码", example = "1") Integer pageNum,
                                 @ApiParam(name = "pageSize", value = "分页每页大小", example = "10") Integer pageSize,
                                 @ApiParam(name = "sortField", value = "排序字段", example = "id") String sortField,
                                 @ApiParam(name = "sortType", value = "排序方式", example = "desc") String sortType) {
        Page<ContractInitialCompleteDto> pager = PageUtil.genPager(pageNum, pageSize, sortField, sortType);
        ContractInitialCompleteDto c = BeanUtil.copyProperties(condition, ContractInitialCompleteDto.class);
        Page<ContractInitialCompleteDto> page = contractInitialCompleteService.page(pager, c);
        Page<ContractInitialCompleteVo> vos = PageUtil.copyPage(page, ContractInitialCompleteVo.class);
        return ResponseDto.getSuccessResponseDto(vos);
    }

    @ApiOperation(value = "根据条件搜索初始合同执行-完结（分页）")
    @GetMapping("/search")
    public ResponseDto<Page<ContractInitialCompleteVo>> search(ContractInitialCompleteCriteria condition,
                                 @ApiParam(name = "pageNum", value = "分页页码", example = "1") Integer pageNum,
                                 @ApiParam(name = "pageSize", value = "分页每页大小", example = "10") Integer pageSize,
                                 @ApiParam(name = "sortField", value = "排序字段", example = "id") String sortField,
                                 @ApiParam(name = "sortType", value = "排序方式", example = "desc") String sortType) {
        Page<ContractInitialCompleteDto> pager = PageUtil.genPager(pageNum, pageSize, sortField, sortType);
        Map<String, Object> c = BeanUtil.beanToMap(condition);
        Page<ContractInitialCompleteDto> page = contractInitialCompleteService.page(pager, c);
        Page<ContractInitialCompleteVo> vos = PageUtil.copyPage(page, ContractInitialCompleteVo.class);
        return ResponseDto.getSuccessResponseDto(vos);
    }

    @SneakyThrows
    @ApiOperation(value = "根据条件导出初始合同执行-完结")
    @GetMapping("/export")
    public void export(ContractInitialCompleteCriteria condition) {
        try {
            assert request != null;
            ContractInitialCompleteDto c = BeanUtil.copyProperties(condition, ContractInitialCompleteDto.class);
            List<ContractInitialCompleteDto> page = contractInitialCompleteService.list(c);
            String file = "导出初始合同执行-完结-" + DateUtil.today() + ".xlsx";
            String name = URLEncoder.encode(file, StandardCharsets.UTF_8.name());
            List<String> head = new ArrayList<>();
            head.add("ID");
            for (Field f : ContractInitialCompleteVo.class.getDeclaredFields()) {
                f.setAccessible(true);
                ApiModelProperty amp = f.getAnnotation(ApiModelProperty.class);
                if (amp != null) {
                    head.add(amp.value());
                }
            }
            head.add("创建时间");
            head.add("最后修改时间");
            List<List<?>> data = new ArrayList<>();
            if (CollUtil.isNotEmpty(page)) {
                for (ContractInitialCompleteDto dto : page) {
                    ContractInitialCompleteVo vo = BeanUtil.copyProperties(dto, ContractInitialCompleteVo.class);
                    List<Serializable> row = new ArrayList<>();
                    row.add(String.valueOf(dto.getId()));
                    for (Field f : ContractInitialCompleteVo.class.getDeclaredFields()) {
                        f.setAccessible(true);
                        ApiModelProperty amp = f.getAnnotation(ApiModelProperty.class);
                        if (amp != null) {
                            String v = ExcelTool.convertValue(f.get(vo), amp);
                            row.add(v);
                        }
                    }
                    row.add(DateUtil.formatDateTime(dto.getCreateTime()));
                    row.add(DateUtil.formatDateTime(dto.getUpdateTime()));
                    data.add(row);
                }
            }
            try (ExcelWriter writer = ExcelTool.genExcelWriter(head, data)) {
                response.setHeader("Content-disposition", "attachment; filename=" + name);
                response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                response.setContentType("application/vnd.ms-excel;charset=utf-8");
                writer.flush(response.getOutputStream(), true);
            }
        } catch (Exception e) {
            response.setContentType(new MediaType(MediaType.APPLICATION_JSON, StandardCharsets.UTF_8).toString());
            throw e;
        }
    }

    @SneakyThrows
    @ApiOperation(value = "初始合同执行-完结导入模版下载")
    @GetMapping("/downloadTemplate")
    public void downloadTemplate() {
        try {
            assert request != null;
            String file = "初始合同执行-完结导入模版-" + DateUtil.today() + ".xlsx";
            String name = URLEncoder.encode(file, StandardCharsets.UTF_8.name());
            List<String> head = new ArrayList<>();
            for (Field f : ContractInitialCompleteVo.class.getDeclaredFields()) {
                f.setAccessible(true);
                ApiModelProperty amp = f.getAnnotation(ApiModelProperty.class);
                NotBlank notBlank = f.getAnnotation(NotBlank.class);
                NotNull notNull = f.getAnnotation(NotNull.class);
                if (amp != null) {
                    String label = amp.value();
                    if (notBlank != null || notNull != null) {
                        label = "*" + label;
                    }
                    head.add(label);
                }
            }
            try (ExcelWriter writer = ExcelTool.genExcelWriter(head, new ArrayList<>())) {
                response.setHeader("Content-disposition", "attachment; filename=" + name);
                response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                response.setContentType("application/vnd.ms-excel;charset=utf-8");
                writer.flush(response.getOutputStream(), true);
            }
        } catch (Exception e) {
            response.setContentType(new MediaType(MediaType.APPLICATION_JSON, StandardCharsets.UTF_8).toString());
            throw e;
        }
    }

    @SneakyThrows
    @ApiOperation(value = "导入初始合同执行-完结数据")
    @GetMapping("/importData")
    public ResponseDto<JSONObject> importData(@ApiParam(name = "file", required = true, value = "文件") @RequestPart(value = "file") MultipartFile file) {
        Workbook book = WorkbookUtil.createBook(file.getInputStream());
        Sheet sheet = WorkbookUtil.getOrCreateSheet(book, 0);
        Font errFont = book.createFont();
        errFont.setColor(Font.COLOR_RED);
        CellStyle errStyle = book.createCellStyle();
        errStyle.setFont(errFont);
        int rowNums = 0;
        int failed = 0;
        Field[] fields = ContractInitialCompleteVo.class.getDeclaredFields();
        JSONObject res = new JSONObject();
        Map<Integer, String> result = new HashMap<>();
        for (int line = 1; line < sheet.getPhysicalNumberOfRows(); line++) {
            rowNums++;
            Row row = RowUtil.getOrCreateRow(sheet, line);
            Cell errCell = CellUtil.getOrCreateCell(row, fields.length);
            try {
                ContractInitialCompleteDto o = new ContractInitialCompleteDto();
                int i = 0;
                while (i < fields.length) {
                    Field f = fields[i];
                    f.setAccessible(true);
                    ApiModelProperty amp = f.getAnnotation(ApiModelProperty.class);
                    if (amp != null) {
                        String v = Constants.df.formatCellValue(CellUtil.getOrCreateCell(row, i));
                        ValidatorUtil.checkFieldValue(f, v, amp.value());
                        f.set(o, v);
                        i++;
                    }
                }
                contractInitialCompleteService.save(o);
                result.put(line, "导入成功");
            } catch (Throwable e) {
                ResponseDto<String> r = ExceptionUtil.render(e);
                errCell.setCellStyle(errStyle);
                errCell.setCellValue(r.getMessage());
                failed++;
                result.put(line, r.getMessage());
            }
        }
        res.put("total", rowNums);
        res.put("success", rowNums - failed);
        res.put("failure", failed);
        res.put("result", result);
        return ResponseDto.getSuccessResponseDto(res);
    }

}
